package es.uned.etsii.si3.taller.servlets;

import java.sql.SQLException;
import java.util.List;

import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import com.opensymphony.xwork2.ActionSupport;

import es.uned.etsii.si3.taller.Cliente;
import es.uned.etsii.si3.taller.Empleado;
import es.uned.etsii.si3.taller.FactoriaDAO;
import es.uned.etsii.si3.taller.FactoriaFunciones;
import es.uned.etsii.si3.taller.Provincia;
import es.uned.etsii.si3.taller.Usuario;
import es.uned.etsii.si3.taller.Empleado.Categoria;
import es.uned.etsii.si3.taller.misc.ProporcionaFuncionalidad;

public class UsuarioOperacionesAdmin
	extends ActionSupport
{
	private static final long serialVersionUID = 1L;
	
	private Usuario usuario = null;
	private Usuario usuarioEncontrado = null;
	private String variableActualizable;
	private boolean buscamosClientes;
	private List<Usuario> listadoUsuarios;
	private boolean esPopup = false;
	private int usuarioEscogido = 0;

	/* EMPIEZA: Getters y setters para los atributos de los formularios */
	public Usuario getUsuario() {
		return usuario;
	}
	
	public void setUsuario(Usuario usuarioWeb) {
		usuario = usuarioWeb;
	}
	
	public List<Usuario> getListadoUsuarios() {
		return listadoUsuarios;
	}
	
	public String getActualizar() {
		return variableActualizable;
	}
	
	public void setActualizar(String variable) {
		variableActualizable = variable;
	}
	
	public void setBuscamosClientes(boolean cl) {
		buscamosClientes = cl;
	}
	
	public boolean getBuscamosClientes() {
		return buscamosClientes;
	}
	
	public boolean getEsPopup() {
		return esPopup;
	}
	
	public void setEsPopup(boolean es) {
		esPopup = es;
	}
	
	public int getUsuarioEscogido() {
		return usuarioEscogido;
	}
	
	public void setUsuarioEscogido(int u) {
		usuarioEscogido = u;
	}
	
	// Los siguientes métodos son para la redirección a formularios de creación
	// de empleados y clientes
	public boolean esClienteNuevo() {
		return true;
	}
	
	public boolean esEmpleadoNuevo() {
		return true;
	}
	
	public boolean listoParaAceptar() {
		return false;
	}
	
	public int provinciaParaCliente() {
		return 0;
	}
	
	public Categoria[] getListaCategorias() {
		return Categoria.values();
	}
	
	public List<Provincia> getListaProvincias() {
		try {
			return Provincia.hacerListaProvincias();
		} catch (SQLException e) {
			addActionError("No se pudo generar la lista de provincias: " + e.toString());
			return null;
		}
	}
	
	/* TERMINA: Getters y setters para los atributos de los formularios */

	/**
	 * Validación de datos de entrada
	 */
	
	@Override
	public void validate() {
		
		if (usuario != null) {
			String nombreUsuario = usuario.getUsuario();
			String email = usuario.getEmail();
			String pass  = usuario.getPassword();
			
			if ((nombreUsuario != null) && (nombreUsuario.trim().isEmpty())) {
				usuario.setUsuario(null);
			}
			
			if ((email != null) && email.trim().isEmpty()) {
				usuario.setEmail(null);
			}

			if ((pass != null) && pass.trim().isEmpty()) {
				usuario.setPassword(null);
			}
		}
		
		if (usuarioEscogido != 0) {
			try {
				usuarioEncontrado = FactoriaDAO.recuperar(Usuario.class, usuarioEscogido);
				if (usuarioEncontrado == null) {
					// No debería pasar, porque esto viene de una lista de valores encontrados en la BD
					addFieldError("usuarioEscogido", "El usuario escogido no existe - error grave");
					usuarioEscogido = 0;
				}
			} catch (SQLException e) {
				addActionError("Al intentar recuperar el usuario escogido: " + e.toString());
			}
		}
		if (usuario == null ){
			setUsuario(usuarioEncontrado);
		}
	}
	
	public String display() {
		return NONE;
	}
	
	public String displayPopup() {
		esPopup = true;
		
		return display();
	}
	
	@SuppressWarnings("unchecked")
	public String buscar() {
		try {
			String usuarioLike = null;
			String emailLike = null;
			boolean restricciones = esPopup;

			QueryBuilder<Usuario, Integer> usuarioQb = FactoriaDAO.getDao(Usuario.class).queryBuilder();			
			Where<Usuario, Integer> whereUsuario = usuarioQb.where();
			
			if (usuario.getUsuario() != null)
				usuarioLike = "%" + usuario.getUsuario() + "%";
			if (usuario.getEmail() != null)
				emailLike = "%" + usuario.getEmail() + "%";
			
			if (usuario.getPassword() != null) {
				addActionMessage("No se usa la clave para las búsquedas");
			}
			
			if ((usuarioLike != null) || (emailLike != null)) {
				if ((usuarioLike != null) && (emailLike != null))
					whereUsuario.or(
							whereUsuario.like(Usuario.USUARIO_FIELD_NAME, usuarioLike),
							whereUsuario.like(Usuario.EMAIL_FIELD_NAME, emailLike));
				else if (usuarioLike != null)
					whereUsuario.like(Usuario.USUARIO_FIELD_NAME, usuarioLike);
				else
					whereUsuario.like(Usuario.EMAIL_FIELD_NAME, emailLike);
				whereUsuario.and().eq(Usuario.ACTIVO_FIELD_NAME, true);
				if (esPopup)
					whereUsuario.and();
				else
					restricciones = true;
			}

			if (esPopup) {
				if (getBuscamosClientes()) {
					QueryBuilder<Cliente, Integer> clienteQb = FactoriaDAO.getDao(Cliente.class).queryBuilder();

					clienteQb.selectColumns(Cliente.ID_USUARIO_FIELD_NAME);

					whereUsuario.eq(Usuario.ESCLIENTE_FIELD_NAME, true)
					.and()
					.notIn(Usuario.ID_FIELD_NAME, clienteQb);
				}
				else {
					QueryBuilder<Empleado, Integer> empleadoQb = FactoriaDAO.getDao(Empleado.class).queryBuilder();

					empleadoQb.selectColumns(Empleado.ID_USUARIO_FIELD_NAME);


					whereUsuario.eq(Usuario.ESCLIENTE_FIELD_NAME, false)
					.and()
					.notIn(Usuario.ID_FIELD_NAME, empleadoQb);
				}
			}
			
			if (!restricciones)
				addActionError("Debe introducir alguna restricción");
			else
				listadoUsuarios = usuarioQb.query();
			
		} catch (SQLException e) {
			addActionError(e.toString());
		}

		return SUCCESS;
	}
	
	public String buscarPopup() {
		esPopup = true;
		
		return buscar();
	}
	
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.ADMIN_MODIFICAR_USUARIO)
	public String modificar() {
		if ((usuario != null) && (usuarioEncontrado != null)) {
			boolean goOn = true;

			if (usuario.getUsuario() == null) {
				addFieldError("usuario.usuario", "El campo de usuario no puede estar vacío");
				goOn = false;
			}
			if (usuario.getEmail() == null) {
				addFieldError("usuario.email", "El campo de email no puede estar vacío");
				goOn = false;
			}
			
			if (goOn) {
				try {
					Usuario u = Usuario.buscarPorNombreUsuario(usuario.getUsuario());
					if (u.getId() != usuarioEncontrado.getId())
						addFieldError("usuario.usuario", "Ya existe otro usuario con ese mismo identificador");
				} catch (SQLException e) {
					addActionError("Error durante el proceso de validación: " + e.toString());
				}
			}
			
			if (hasActionErrors())
				return INPUT;
		}
		
		if ((usuarioEncontrado == null) || (usuario == null)) {
			addActionError("Error general al modificar: faltan datos");
			return INPUT;
		}
		
		try {
			usuarioEncontrado.actualizar(usuario);
			addActionMessage(String.format("Actualizados los datos del usuario %s", usuarioEncontrado.getUsuario()));
			
			setUsuario(null);
			usuarioEscogido = 0;
		} catch (SQLException e) {
			addActionError("Al intentar actualizar los datos del usuario: " + e.toString());
		}
		
		return SUCCESS;
	}
	
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.ADMIN_BAJA_USUARIO)
	public String baja() {
		if (usuarioEncontrado == null) {
			addActionError("Error general al dar de baja: faltan datos");
			return INPUT;
		}
		
		if (!usuarioEncontrado.getActivo()) {
			addActionError(String.format("El usuario %s ya estaba dado de baja", usuarioEncontrado.getUsuario()));
			return INPUT;
		}
		
		try {
			usuarioEncontrado.desactivar();
			
			addActionMessage(String.format("Dado de baja el usuario %s", usuarioEncontrado.getUsuario()));
		} catch (SQLException e) {
			addActionError("Al intentar dar de baja al usuario: " + e.toString());
		}
		
		return SUCCESS;
	}
	
	private void nuevoUsuario(boolean esCliente) {
		if (usuario == null) {
			addActionError("No hay datos de usuario");
		}
		else {
			if (usuario.getUsuario() == null)
				addFieldError("usuario.usuario", "Falta el nombre de usuario");
			if (usuario.getEmail() == null)
				addFieldError("usuario.email", "Falta la dirección de correo");
			if (usuario.getPassword() == null)
				addFieldError("usuario.password", "Falta la clave");
		}
		
		if (!hasActionErrors() && !hasFieldErrors()) {
			try {
				Usuario us = Usuario.buscarPorNombreUsuario(usuario.getUsuario());
				
				if (us != null)
					addFieldError("usuario.usuario", "Este nombre de usuario ya está en uso");
				else {
					Usuario.crear(usuario.getUsuario(), usuario.getPassword(), usuario.getEmail(), esCliente)
					       .setActivo(true);
				}
			} catch (SQLException e) {
				addActionError("Intentando crear el usuario: " + e.toString());
			}
		}
	}
	
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.ADMIN_NUEVO_USUARIO)
	public String nuevoCliente() {
		nuevoUsuario(true);
		
		if (hasActionErrors() || hasFieldErrors())
			return INPUT;
		
		return SUCCESS;
	}
	
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.ADMIN_NUEVO_USUARIO)
	public String nuevoEmpleado() {
		nuevoUsuario(false);
		
		if (hasActionErrors() || hasFieldErrors())
			return INPUT;
		
		return SUCCESS;
	}
}